using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Path = System.IO.Path;
using System.Collections.Generic;

namespace ETTools
{
    public static class ProcessHelper
    {
        public static string basePath = AppContext.BaseDirectory;
        public static Process Run(string exe, string arguments, string workingDirectory = ".", bool waitExit = false)
        {
            try
            {
                bool redirectStandardOutput = true;
                bool redirectStandardError = true;
                bool useShellExecute = false;
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    redirectStandardOutput = false;
                    redirectStandardError = false;
                    useShellExecute = true;
                }

                if (waitExit)
                {
                    redirectStandardOutput = true;
                    redirectStandardError = true;
                    useShellExecute = false;
                }
                
                ProcessStartInfo info = new ProcessStartInfo
                {
                    FileName = exe,
                    Arguments = arguments,
                    CreateNoWindow = true,
                    UseShellExecute = useShellExecute,
                    WorkingDirectory = workingDirectory,
                    RedirectStandardOutput = redirectStandardOutput,
                    RedirectStandardError = redirectStandardError,
                };
                
                Process process = Process.Start(info);

                if (waitExit)
                {
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        throw new Exception($"{process.StandardOutput.ReadToEnd()} {process.StandardError.ReadToEnd()}");
                    }
                }

                return process;
            }
            catch (Exception e)
            {
                throw new Exception($"dir: {Path.GetFullPath(workingDirectory)}, command: {exe} {arguments}", e);
            }
        }

        public static string MakeRelative(string fromDirectory, string toPath)
        {
            if (fromDirectory == null)
                throw new ArgumentNullException("fromDirectory");
 
            if (toPath == null)
                throw new ArgumentNullException("toPath");
 
            bool isRooted = (Path.IsPathRooted(fromDirectory) && Path.IsPathRooted(toPath));
 
            if (isRooted)
            {
                bool isDifferentRoot = (string.Compare(Path.GetPathRoot(fromDirectory), Path.GetPathRoot(toPath), true) != 0);
 
                if (isDifferentRoot)
                    return toPath;
            }
 
            List<string> relativePath = new List<string>();
            string[] fromDirectories = fromDirectory.Split(Path.DirectorySeparatorChar);
 
            string[] toDirectories = toPath.Split(Path.DirectorySeparatorChar);
 
            int length = Math.Min(fromDirectories.Length, toDirectories.Length);
 
            int lastCommonRoot = -1;
 
            // find common root
            for (int x = 0; x < length; x++)
            {
                if (string.Compare(fromDirectories[x], toDirectories[x], true) != 0)
                    break;
 
                lastCommonRoot = x;
            }
 
            if (lastCommonRoot == -1)
                return toPath;
 
            // add relative folders in from path
            for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)
            {
                if (fromDirectories[x].Length > 0)
                    relativePath.Add("..");
            }
 
            // add to folders to path
            for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)
            {
                relativePath.Add(toDirectories[x]);
            }
 
            // create relative path
            string[] relativeParts = new string[relativePath.Count];
            relativePath.CopyTo(relativeParts, 0);
 
            string newPath = string.Join(Path.DirectorySeparatorChar.ToString(), relativeParts);
 
            return newPath;
        }
        public static string MakeAbsolute(string fromPath, string toPath)
        {
            string temp = Path.Combine(fromPath, toPath);
            return Path.GetFullPath(temp);
        }

    }
}